﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class GroupingPipes
	{
		public GroupingPipes(List<Pipe> listPipe)
		{
			this.originalPipes = listPipe;
		}

		public List<List<Pipe>> GroupedPipes
		{
			get
			{
				return this.groupedPipes;
			}
		}

		public void SpliteAndGroupPipes()
		{
			List<List<Pipe>> paralleledPipes = this.GetParalleledPipes();
			this.groupedPipes = new List<List<Pipe>>();
			foreach (List<Pipe> parallelPipes in paralleledPipes)
			{
				this.GroupingParallelPipes(parallelPipes, ref this.groupedPipes);
			}
		}

		private List<List<Pipe>> GetParalleledPipes()
		{
			List<List<Pipe>> result = new List<List<Pipe>>();
			foreach (Pipe pipe in this.originalPipes)
			{
				this.JudgeAndGroupPipe(ref result, pipe);
			}
			return result;
		}

		private void GroupingParallelPipes(List<Pipe> parallelPipes, ref List<List<Pipe>> groupParallelPipes)
		{
			if (parallelPipes == null || parallelPipes.Count < 1)
			{
				return;
			}
			List<Pipe> list = new List<Pipe>();
			if (parallelPipes.Count == 1)
			{
				list.Add(parallelPipes.First<Pipe>());
				groupParallelPipes.Add(list);
				return;
			}
			parallelPipes = (from pipe in parallelPipes
			orderby this.GetPipeLength(pipe)
			select pipe).ToList<Pipe>();
			XYZ pipeLineMiddlePoint = this.GetPipeLineMiddlePoint(parallelPipes.First<Pipe>());
			List<Pipe> list2 = new List<Pipe>();
			list.Add(parallelPipes.First<Pipe>());
			for (int i = 1; i < parallelPipes.Count; i++)
			{
				if (this.PointBeOnPipe(pipeLineMiddlePoint, parallelPipes[i]))
				{
					list.Add(parallelPipes[i]);
				}
				else
				{
					list2.Add(parallelPipes[i]);
				}
			}
			groupParallelPipes.Add(list);
			if (list2.Count > 0)
			{
				this.GroupingParallelPipes(list2, ref this.groupedPipes);
			}
		}

		private bool PointBeOnPipe(XYZ middlePoint, Pipe pipe)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			XYZ project = hypiping.GetProject(middlePoint, true);
			return hypiping.IsPointOnPipingCurve(project);
		}

		private XYZ GetPipeLineMiddlePoint(Pipe pipe)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			XYZ origin = hypiping.StartConnector.Origin;
			XYZ origin2 = hypiping.EndConnector.Origin;
			return origin.Add(origin2) / 2.0;
		}

		private double GetPipeLength(Pipe pipe)
		{
			return new YJKPiping<Pipe>(pipe).GetLocationCurve().ApproximateLength;
		}

		private void JudgeAndGroupPipe(ref List<List<Pipe>> parallelPipes, Pipe pipe)
		{
			if (parallelPipes == null)
			{
				parallelPipes = new List<List<Pipe>>();
			}
			if (parallelPipes.Count < 1)
			{
				List<Pipe> list = new List<Pipe>();
				list.Add(pipe);
				parallelPipes.Add(list);
				return;
			}
			bool flag = false;
			foreach (List<Pipe> list2 in parallelPipes)
			{
				if (list2 != null && list2.Count >= 1)
				{
					flag = this.BeParallelTwoPipes(list2.First<Pipe>(), pipe);
					if (flag)
					{
						list2.Add(pipe);
						break;
					}
				}
			}
			if (!flag)
			{
				List<Pipe> list3 = new List<Pipe>();
				list3.Add(pipe);
				parallelPipes.Add(list3);
			}
		}

		private bool BeParallelTwoPipes(Pipe pipe1, Pipe pipe2)
		{
			return new YJKPiping<Pipe>(pipe1).IsParallel(pipe2);
		}

		private XYZ GetPipeVector(Pipe pipe)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			XYZ origin = hypiping.StartConnector.Origin;
			XYZ origin2 = hypiping.EndConnector.Origin;
			return origin.Subtract(origin2).Normalize();
		}

		private List<Pipe> originalPipes;

		private List<List<Pipe>> groupedPipes;
	}
}
